package com.yzy.fly.boot.banner;

import com.yzy.fly.function.logging.Log;
import com.yzy.fly.function.logging.LogException;
import com.yzy.fly.function.logging.LogFactory;

import java.lang.reflect.Constructor;

public final class BannerFactory {
    private static Log log = LogFactory.getLog(BannerFactory.class);

    private static Constructor<? extends Banner> bannerConstructor;

    static {
        tryImplementation(BannerFactory::useDefaultBanner);
        tryImplementation(BannerFactory::useNoBanner);
    }

    public BannerFactory() {
        // disable construction
    }

//    public static Banner getBanner(Class<?> clazz) {
//        return getBanner(clazz.getName());
//    }

    public static Banner getBanner() {
        try {
            return bannerConstructor.newInstance();
        } catch (Throwable t) {
            Class<? extends Banner> bannerClass = bannerConstructor.getDeclaringClass();
            throw new LogException("Error creating banner for banner " + bannerClass + ".  Cause: " + t, t);
        }
    }

    public static synchronized void useCustomBanner(Class<? extends Banner> clazz) {
        setImplementation(clazz);
    }

    public static synchronized void useDefaultBanner() {
        setImplementation(DefaultBannerImpl.class);
    }

    public static synchronized void useNoBanner() {
        setImplementation(NoBannerImpl.class);
    }

    private static void tryImplementation(Runnable runnable) {
        if (bannerConstructor == null) {
            try {
                runnable.run();
            } catch (Throwable t) {
                // ignore
            }
        }
    }

    private static void setImplementation(Class<? extends Banner> implClass) {
        try {
            Constructor<? extends Banner> candidate = implClass.getConstructor();
//            Banner banner = candidate.newInstance();
            if (log.isDebugEnabled()) {
                log.debug("Banner initialized using '" + implClass + "' adapter.");
            }
            bannerConstructor = candidate;
        } catch (Throwable t) {
            throw new LogException("Error setting Banner implementation.  Cause: " + t, t);
        }
    }

}
